package com.five.wisdomClass.ws;

import com.alibaba.fastjson.JSON;
import com.five.wisdomClass.config.GetHttpSessionConfig;
import com.five.wisdomClass.utils.MessageUtils;
import com.five.wisdomClass.ws.pojo.Message;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpSession;
import jakarta.websocket.*;
import jakarta.websocket.server.PathParam;
import jakarta.websocket.server.ServerEndpoint;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.RequestParam;

import java.net.URI;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;

@ServerEndpoint(value = "/chat/{token}", configurator = GetHttpSessionConfig.class)
@Component
public class ChatEndpoint {

    private static RedisTemplate<String,String> redisTemplate;

    @Autowired
    public void setRedisTemplate(RedisTemplate<String,String> redisTemplate){
        ChatEndpoint.redisTemplate = redisTemplate;
    }

    private static final Map<String, Session> onlineUsers = new ConcurrentHashMap<>();
    private HttpSession httpSession;

    @OnOpen
    public void onOpen(Session session , @PathParam("token") String token,EndpointConfig config) {
//        this.httpSession = (HttpSession) config.getUserProperties().get(HttpSession.class.getName());
//        String user = (String) this.httpSession.getAttribute("name");
        String user = redisTemplate.opsForValue().get(token);
        //1，将session进行保存到最上面定义的onlineUsers对象。注意onlineUsers对象的唯一数据来源就是下一行
        onlineUsers.put(user,session);
        //2，广播消息。需要将登陆的所有的用户推送给所有的用户。也就是获取在线的好友列表。MessageUtils是我们写的工具类
        String message = MessageUtils.getMessage(true,null, getFriends());
        broadcastAllUsers(message);
    }

    @OnMessage
    public void onMessage(String message,@PathParam("token") String token) {
        try {
            //将消息推送给指定的用户
            Message msg = JSON.parseObject(message, Message.class);
            //获取 消息接收方的用户名
            String toName = msg.getToName();
            String messageTemp = msg.getMessage();
            //获取消息接收方用户对象的session对象
            Session session = onlineUsers.get(toName);
//            String user = (String) this.httpSession.getAttribute("user");
            String user = redisTemplate.opsForValue().get(token);
            String msg1 = MessageUtils.getMessage(false, user, messageTemp);
            // 发送消息，getBasicRemote().sendText()方法是官方写好的。getBasicRemote表示同步的消息
            session.getBasicRemote().sendText(msg1);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @OnClose
    public void onClose(Session session,@PathParam("token") String token) {
        //1,从onlineUsers中删除当前用户的session对象，表示当前用户下线了
//        String user = (String) this.httpSession.getAttribute("user");
        String user = redisTemplate.opsForValue().get(token);
        onlineUsers.remove(user);
        //2,通知其他所有的用户，当前用户下线了
        String message = MessageUtils.getMessage(true,null, getFriends());
        broadcastAllUsers(message);
    }

    public Set getFriends() {
        // 拿到该Map集合(onlineUsers是最上面定义的Map集合)的所有key，且key的返回值刚好用Set类型接收。这个Map的所有key，其实就是写死的user字符串
        Set<String> set = onlineUsers.keySet();
        return set;
    }

    // 广播消息的具体逻辑
    private void broadcastAllUsers(String message) {
        try {
            //遍历最上面定义的onlineUsers对象的数据
            Set<Map.Entry<String, Session>> entries = onlineUsers.entrySet();
            for (Map.Entry<String, Session> entry : entries) {
                //获取到所有用户对应的session对象
                Session session = entry.getValue();
                //发送消息，getBasicRemote().sendText()方法是官方写好的。getBasicRemote表示同步的消息
                session.getBasicRemote().sendText(message);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
